﻿//===================================================================================
// Copyright (c) Ryan Garrett.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===================================================================================

using System;
using System.Collections.Generic;

namespace Caffeine.Core.Test.TestModel
{
    public class ModelForEventSequenceTesting : ModelBase
    {
        private readonly ModelProperty<ModelForEventSequenceTesting> _child;
        private readonly ModelProperty<ModelForEventSequenceTesting> _muteChild;
        private readonly ModelProperty<String> _property;
        private readonly ModelProperty<Int32> _onBeforeParentChangedIndex;
        private readonly ModelProperty<Int32> _onParentChangedIndex;
        private readonly ModelProperty<Int32> _onIsDirtyChangedIndex;
        private readonly ModelProperty<Int32> _onIsDirtyWithinChangedIndex;
        private readonly ModelProperty<Int32> _onIsInvalidChangedIndex;
        private readonly ModelProperty<Int32> _onIsInvalidWithinChangedIndex;
        private readonly ModelProperty<Int32> _onParentPropertyChangedIndex;
        private readonly ModelProperty<Int32> _onAssignedToPropertyIndex;
        private readonly ModelProperty<Int32> _onCommittedToPropertyIndex;
        private readonly ModelProperty<Int32> _onMarkedForRemovalFromPropertyIndex;
        private readonly ModelProperty<Int32> _onRemovedFromParentPropertyIndex;
        private readonly ModelProperty<Int32> _onPropertyIsDefaultChangedIndex;
        private readonly ModelProperty<Int32> _onPropertyIsDirtyChangedIndex;
        private readonly ModelProperty<Int32> _onPropertyIsInvalidChangedIndex;
        private readonly ModelProperty<Int32> _onPropertyValueChangedIndex;
        private readonly ModelProperty<Int32> _onPropertyCommittedValueChangedIndex;

        public ModelForEventSequenceTesting()
        {
            _child = RegisterProperty<ModelForEventSequenceTesting>("Child");
            _muteChild = RegisterProperty<ModelForEventSequenceTesting>("MuteChild", ModelPropertyBehaviors.SetsParentIsDirty.AddBehavior(ModelPropertyBehaviors.SetsParentIsInvalid));
            _property = RegisterProperty<String>("Property");
            _onBeforeParentChangedIndex = RegisterProperty<Int32>("OnBeforeParentChangedIndex", ModelPropertyBehaviors.IsResettable);
            _onParentChangedIndex = RegisterProperty<Int32>("OnParentChangedIndex", ModelPropertyBehaviors.IsResettable);
            _onIsDirtyChangedIndex = RegisterProperty<Int32>("OnIsDirtyChangedIndex", ModelPropertyBehaviors.IsResettable);
            _onIsDirtyWithinChangedIndex = RegisterProperty<Int32>("OnIsDirtyWithinChangedIndex", ModelPropertyBehaviors.IsResettable);
            _onIsInvalidChangedIndex = RegisterProperty<Int32>("OnIsInvalidChangedIndex", ModelPropertyBehaviors.IsResettable);
            _onIsInvalidWithinChangedIndex = RegisterProperty<Int32>("OnIsInvalidWithinChangedIndex", ModelPropertyBehaviors.IsResettable);
            _onParentPropertyChangedIndex = RegisterProperty<Int32>("OnParentPropertyChangedIndex", ModelPropertyBehaviors.IsResettable);
            _onAssignedToPropertyIndex = RegisterProperty<Int32>("OnAssignedToPropertyIndex", ModelPropertyBehaviors.IsResettable);
            _onCommittedToPropertyIndex = RegisterProperty<Int32>("OnCommittedToPropertyIndex", ModelPropertyBehaviors.IsResettable);
            _onMarkedForRemovalFromPropertyIndex = RegisterProperty<Int32>("OnMarkedForRemovalFromPropertyIndex", ModelPropertyBehaviors.IsResettable);
            _onRemovedFromParentPropertyIndex = RegisterProperty<Int32>("OnRemovedFromParentPropertyIndex", ModelPropertyBehaviors.IsResettable);
            _onPropertyIsDirtyChangedIndex = RegisterProperty<Int32>("OnPropertyIsDirtyChangedIndex", ModelPropertyBehaviors.IsResettable);
            _onPropertyIsDefaultChangedIndex = RegisterProperty<Int32>("OnPropertyIsDefaultChangedIndex", ModelPropertyBehaviors.IsResettable);
            _onPropertyIsInvalidChangedIndex = RegisterProperty<Int32>("OnPropertyIsInvalidChangedIndex", ModelPropertyBehaviors.IsResettable);
            _onPropertyValueChangedIndex = RegisterProperty<Int32>("OnPropertyValueChangedIndex", ModelPropertyBehaviors.IsResettable);
            _onPropertyCommittedValueChangedIndex = RegisterProperty<Int32>("OnPropertyCommittedValueChangedIndex", ModelPropertyBehaviors.IsResettable);
        }

        public CallCounter Counter
        {
            get;
            set;
        }

        public ModelProperty<ModelForEventSequenceTesting> Child
        {
            get
            {
                return _child;
            }
        }

        public ModelProperty<ModelForEventSequenceTesting> MuteChild
        {
            get
            {
                return _muteChild;
            }
        }

        public ModelProperty<String> Property
        {
            get
            {
                return _property;
            }
        }

        public ModelProperty<Int32> OnBeforeParentChangedIndex
        {
            get
            {
                return _onBeforeParentChangedIndex;
            }
        }

        public ModelProperty<Int32> OnParentChangedIndex
        {
            get
            {
                return _onParentChangedIndex;
            }
        }

        public ModelProperty<Int32> OnIsDirtyChangedIndex
        {
            get
            {
                return _onIsDirtyChangedIndex;
            }
        }

        public ModelProperty<Int32> OnIsDirtyWithinChangedIndex
        {
            get
            {
                return _onIsDirtyWithinChangedIndex;
            }
        }

        public ModelProperty<Int32> OnIsInvalidChangedIndex
        {
            get
            {
                return _onIsInvalidChangedIndex;
            }
        }

        public ModelProperty<Int32> OnIsInvalidWithinChangedIndex
        {
            get
            {
                return _onIsInvalidWithinChangedIndex;
            }
        }

        public ModelProperty<Int32> OnParentPropertyChangedIndex
        {
            get
            {
                return _onParentPropertyChangedIndex;
            }
        }

        public ModelProperty<Int32> OnAssignedToPropertyIndex
        {
            get
            {
                return _onAssignedToPropertyIndex;
            }
        }

        public ModelProperty<Int32> OnCommittedToPropertyIndex
        {
            get
            {
                return _onCommittedToPropertyIndex;
            }
        }

        public ModelProperty<Int32> OnMarkedForRemovalFromPropertyIndex
        {
            get
            {
                return _onMarkedForRemovalFromPropertyIndex;
            }
        }

        public ModelProperty<Int32> OnRemovedFromParentPropertyIndex
        {
            get
            {
                return _onRemovedFromParentPropertyIndex;
            }
        }

        public ModelProperty<Int32> OnPropertyIsDefaultChangedIndex
        {
            get
            {
                return _onPropertyIsDefaultChangedIndex;
            }
        }

        public ModelProperty<Int32> OnPropertyIsDirtyChangedIndex
        {
            get
            {
                return _onPropertyIsDirtyChangedIndex;
            }
        }

        public ModelProperty<Int32> OnPropertyIsInvalidChangedIndex
        {
            get
            {
                return _onPropertyIsInvalidChangedIndex;
            }
        }

        public ModelProperty<Int32> OnPropertyValueChangedIndex
        {
            get
            {
                return _onPropertyValueChangedIndex;
            }
        }

        public ModelProperty<Int32> OnPropertyCommittedValueChangedIndex
        {
            get
            {
                return _onPropertyCommittedValueChangedIndex;
            }
        }

        public void ResetIndexCounters()
        {
            OnBeforeParentChangedIndex.Value = -1;
            OnParentChangedIndex.Value = -1;
            OnIsDirtyChangedIndex.Value = -1;
            OnIsDirtyWithinChangedIndex.Value = -1;
            OnIsInvalidChangedIndex.Value = -1;
            OnIsInvalidWithinChangedIndex.Value = -1;
            OnParentPropertyChangedIndex.Value = -1;
            OnAssignedToPropertyIndex.Value = -1;
            OnCommittedToPropertyIndex.Value = -1;
            OnMarkedForRemovalFromPropertyIndex.Value = -1;
            OnRemovedFromParentPropertyIndex.Value = -1;
            OnPropertyIsDirtyChangedIndex.Value = -1;
            OnPropertyIsDefaultChangedIndex.Value = -1;
            OnPropertyIsInvalidChangedIndex.Value = -1;
            OnPropertyValueChangedIndex.Value = -1;
            OnPropertyCommittedValueChangedIndex.Value = -1;
            Counter.Index = 0;
        }

        #region View Model Events

        protected override void OnIsDirtyChanged()
        {
            OnIsDirtyChangedIndex.Value = Counter.Index++;
            base.OnIsDirtyChanged();
        }

        protected override void OnIsDirtyWithinChanged()
        {
            OnIsDirtyWithinChangedIndex.Value = Counter.Index++;
            base.OnIsDirtyWithinChanged();
        }

        protected override void OnIsInvalidChanged()
        {
            OnIsInvalidChangedIndex.Value = Counter.Index++;
            base.OnIsInvalidChanged();
        }

        protected override void OnIsInvalidWithinChanged()
        {
            OnIsInvalidWithinChangedIndex.Value = Counter.Index++;
            base.OnIsInvalidWithinChanged();
        }

        #endregion

        #region Child View Model Events

        protected override void OnBeforeParentChanged()
        {
            OnBeforeParentChangedIndex.Value = Counter.Index++;
            base.OnBeforeParentChanged();
        }

        protected override void OnParentChanged()
        {
            OnParentChangedIndex.Value = Counter.Index++;
            base.OnParentChanged();
        }

        protected override void OnParentPropertyChanged(ModelScalarPropertyBase parentProperty)
        {
            OnParentPropertyChangedIndex.Value = Counter.Index++;
            base.OnParentPropertyChanged(parentProperty);
        }

        protected override void OnAssignedToProperty(ModelScalarPropertyBase parentProperty)
        {
            OnAssignedToPropertyIndex.Value = Counter.Index++;
            base.OnAssignedToProperty(parentProperty);
        }

        protected override void OnCommittedToProperty(ModelScalarPropertyBase parentProperty)
        {
            OnCommittedToPropertyIndex.Value = Counter.Index++;
            base.OnCommittedToProperty(parentProperty);
        }

        protected override void OnMarkedForRemovalFromProperty(ModelScalarPropertyBase parentProperty)
        {
            OnMarkedForRemovalFromPropertyIndex.Value = Counter.Index++;
            base.OnMarkedForRemovalFromProperty(parentProperty);
        }

        protected override void OnRemovedFromParentProperty(ModelScalarPropertyBase parentProperty)
        {
            OnRemovedFromParentPropertyIndex.Value = Counter.Index++;
            base.OnRemovedFromParentProperty(parentProperty);
        }

        #endregion

        #region Property Events

        protected override void OnPropertyIsDefaultChanged(ModelScalarPropertyBase property)
        {
            OnPropertyIsDefaultChangedIndex.Value = Counter.Index++;
            base.OnPropertyIsDefaultChanged(property);
        }

        protected override void OnPropertyIsDirtyChanged(ModelPropertyBase property)
        {
            OnPropertyIsDirtyChangedIndex.Value = Counter.Index++;
            base.OnPropertyIsDirtyChanged(property);
        }

        protected override void OnPropertyIsInvalidChanged(ModelPropertyBase property)
        {
            OnPropertyIsInvalidChangedIndex.Value = Counter.Index++;
            base.OnPropertyIsInvalidChanged(property);
        }

        protected override void OnPropertyValueChanged(ModelScalarPropertyBase property)
        {
            if (property.Name == Property.Name)
            {
                OnPropertyValueChangedIndex.Value = Counter.Index++;
            }

            base.OnPropertyValueChanged(property);
        }

        protected override void OnPropertyCommittedValueChanged(ModelScalarPropertyBase property)
        {
            OnPropertyCommittedValueChangedIndex.Value = Counter.Index++;
            base.OnPropertyCommittedValueChanged(property);
        }

        #endregion

        protected override void OnInitialized()
        {
            Property.ValidationMethod = new PropertyValidationDel<String>
            (
                delegate(ModelProperty<String> property, ref IEnumerable<ValidationError> validationErrors, ref Boolean isValid)
                {
                    validationErrors = new List<ValidationError>(new ValidationError[] { new ValidationError() { ErrorCode = 0, ErrorDescription = "The error" } });
                    isValid = !property.IsDirty && property.IsDefault;
                }
            );

            Reset();

            base.OnInitialized();
        }
    }
}
